package net.cachedb4j.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.crank.crud.criteria.Criterion;
import org.crank.crud.criteria.OrderBy;
import org.crank.crud.join.Join;

public interface BaseGenericDao<T, PK extends Serializable> {

	/**
	 * store in cache temporary, wait for database free
	 * 
	 * @param entity
	 */
	public T persist(T entity);

	public Collection<T> persist(Collection<T> entitis);

	/**
	 * store in cache temporary, wait for cache timeout then store in database
	 * 
	 * @param entity
	 */
	public T save(T entity);

	public Collection<T> save(Collection<T> entitis);

	/**
	 * persist entity to database immediately
	 * 
	 * @param entity
	 */
	public T store(T entity);

	public Collection<T> store(Collection<T> entitis);

	/**
	 * just update cache, wait for database free
	 * @deprecated Use merge
	 * @param entity
	 */
	T update(T entity);

	/**
	 * 
	 * @deprecated Use merge
	 */
	Collection<T> update(Collection<T> entitis);

	/**
	 * update entity to database and cache immediately
	 * 
	 * @param entity
	 * @return
	 */
	public T refresh(T entity);
	
	public T refresh(PK id);

	public Collection<T> refresh(Collection<T> entitis);

	/**
	 * if object existed, call update else call save
	 * 
	 * @param entity
	 */
	public T merge(T entity);

	public Collection<T> merge(Collection<T> entitis);

	/**
	 * 
	 * @param id
	 * @return
	 */
	public T read(PK id);

	public T read(Collection<PK> ids);

	/**
	 * Generic method used to get all objects of a particular type. This is the
	 * same as lookup up all rows in a table.
	 * 
	 * @return List of populated objects
	 */
	List<T> find();

	/**
	 * Allows getting an object using a map of the field and values
	 * 
	 * @param propertyValues
	 * @return List of requested objects.
	 */
	List<T> find(Map<String, Object> propertyValues);

	/**
	 * Allows getting an object using a map of the field and values
	 * 
	 * @param propertyNames
	 *            Names of the fields on which to search.
	 * @param values
	 *            Values of the fields on which this is searching.
	 * @return List of requested objects.
	 */
	List<T> find(String[] propertyNames, Object[] values);

	/**
	 * Does a query such as select yada from [yourclass] where field=value
	 * orderBy field.
	 * 
	 * @param propertyNames
	 *            Names of the fields on which to search.
	 * @param values
	 *            Values of the fields on which this is searching.
	 * @param orderBy
	 *            fields to order by in descending order
	 * @return List of requested objects.
	 */
	List<T> find(String[] propertyNames, Object[] values, String[] orderBy);

	/**
	 * Does a query such as select yada from [yourclass] where field=value
	 * orderBy field.
	 * 
	 * @param propertyValues
	 *            properties of VO to use as filters
	 * @param orderBy
	 *            fields to order by in descending order
	 * @return List of requested objects.
	 */
	List<T> find(Map<String, Object> propertyValues, String[] orderBy);

	/**
	 * Method takes a class object and string field, and value to get a list of
	 * objects. This is like a select "where something = value"
	 * 
	 * @param property
	 *            field in entity
	 * @param value
	 *            value to search on
	 * @return list of the annotated objects
	 */
	List<T> find(String property, Object value);

	int count();

	int count(Criterion... criteria);

	int count(Join[] fetches, Criterion... criteria);

	List<T> find(Criterion... criteria);

	List<T> find(String[] orderBy, Criterion... criteria);

	List<T> searchOrdered(Criterion criteria, String... orderBy);

	List<T> find(List<Criterion> criteria, List<String> orderBy);

	List<T> find(List<Criterion> criteria, String[] orderBy);

	List<T> find(Join[] fetches, String[] orderBy, Criterion... criteria);

	List<T> find(Join[] fetches, Criterion... criteria);

	List<T> find(Join... fetches);

	public List<T> find(Join[] fetches, String[] orderBy, int startPosition,
			int maxResults, Criterion... criteria);

	public List<T> find(Join[] fetches, OrderBy[] orderBy, int startPosition,
			int maxResults, Criterion... criteria);

	public List<T> find(String[] orderBy, int startPosition, int maxResults,
			Criterion... criteria);

	public List<T> find(int startPosition, int maxResults,
			Criterion... criteria);

	public List<T> find(int startPosition, int maxResults);

	List<T> find(OrderBy[] orderBy, int startPosition, int maxResults,
			Criterion... criteria);

	List<T> find(OrderBy[] orderBy, Criterion... criteria);

	/**
	 * remove object in cache first, and query database will return null
	 * 
	 * @param entity
	 */
	void remove(T entity);

	void remove(Collection<T> entitis);

	void remove(PK id);

	/**
	 * remove object immediately
	 * 
	 * @param entity
	 */
	void delete(T entitis);

	void delete(Collection<T> entitis);

	void delete(PK id);

	void run(Runnable runnable);

	void clear();

	void flush();

}
